package com.example.pwj.ffstudy.comm;

import android.animation.Animator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.IntDef;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;


import com.example.pwj.ffstudy.R;
import com.example.pwj.ffstudy.comm.anim.AlphaInAnimation;
import com.example.pwj.ffstudy.comm.anim.BaseAnimation;
import com.example.pwj.ffstudy.comm.anim.ScaleInAnimation;
import com.example.pwj.ffstudy.comm.anim.SlideInBottomAnimation;
import com.example.pwj.ffstudy.comm.anim.SlideInLeftAnimation;
import com.example.pwj.ffstudy.comm.anim.SlideInRightAnimation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by pwj on 2017/8/16.
 */

public abstract class CommAdapter<T> extends RecyclerView.Adapter<CommViewHolder> {
    protected String TAG = CommAdapter.class.getSimpleName();
    protected Context mContext;
    protected int layoutId;
    protected List<T> mData;
    private boolean isOpenAnim;
    private BaseAnimation customAnimator;
    private BaseAnimation setAnimator;
    private boolean isFirstOnly = true;
    private int lastPostion = -1;
    private int mDuration = 300;
    protected static final int NORMAL_VIEW = 0x0001;
    protected static final int HEADER_VIEW = 0x0002;
    protected static final int FOOTER_VIEW = 0x0003;
    private List<View> mHeaderViews = new ArrayList<>();
    private List<View> mFooterViews = new ArrayList<>();
    public static final int ALPHA = 0x0010;
    public static final int SCALE_IN = 0x0011;
    public static final int SLIDE_BOTTOM = 0x0012;
    public static final int SLIDE_LEFT = 0x0013;
    public static final int SLIDE_RIGHT = 0x0014;
    private boolean canLoad;

    @IntDef({ALPHA, SCALE_IN, SLIDE_BOTTOM, SLIDE_LEFT, SLIDE_RIGHT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface AnimType {

    }

    private Interpolator mInterpolator = new LinearInterpolator();

    public CommAdapter(Context context, int layoutId) {
        this(context, layoutId, null);
    }

    public CommAdapter(Context context, int layoutId, List<T> data) {
        this.mContext = context;
        this.layoutId = layoutId;
        this.mData = data == null ? new ArrayList<T>() : data;
    }

    public void addHeader(View header) {
        if (header == null) {
            throw new RuntimeException("header is null");
        }
        if (mHeaderViews.size() == 0) {
            mHeaderViews.add(header);
        }
        notifyDataSetChanged();
    }

    public void removeHeader() {
        if (mHeaderViews.size() != 0) {
            mHeaderViews.remove(0);
        }
        notifyDataSetChanged();
    }

    public void addFooter(View footer) {
        if (footer == null) {
            throw new RuntimeException("footer is null");
        }
        if (mFooterViews.size() == 0) {
            mFooterViews.add(footer);
        }
        notifyDataSetChanged();
    }

    public void removeFooter() {
        if (mFooterViews.size() != 0) {
            mFooterViews.remove(0);
        }
        notifyDataSetChanged();
    }

    public int getHeaderCount() {
        return mHeaderViews.size();
    }

    public int getFooterCount() {
        return mFooterViews.size();
    }

    public void setFirstOnly(boolean firstOnly) {
        isFirstOnly = firstOnly;
    }

    public void openLoadAnimation() {
        this.isOpenAnim = true;
        setAnimator = new AlphaInAnimation();
    }

    public void openLoadAnimation(BaseAnimation animation) {
        this.isOpenAnim = true;
        this.customAnimator = animation;
        setAnimator = new AlphaInAnimation();
    }

    /**
     * @param animationType Anim类中选择动画类型
     */
    public void openLoadAnimation(@AnimType int animationType) {
        this.isOpenAnim = true;
        this.customAnimator = null;
        switch (animationType) {
            case ALPHA:
                setAnimator = new AlphaInAnimation();
                break;
            case SCALE_IN:
                setAnimator = new ScaleInAnimation();
                break;
            case SLIDE_BOTTOM:
                setAnimator = new SlideInBottomAnimation();
                break;
            case SLIDE_LEFT:
                setAnimator = new SlideInLeftAnimation();
                break;
            case SLIDE_RIGHT:
                setAnimator = new SlideInRightAnimation();
                break;
        }
    }

    /**
     * 不好确定这个view只加一个，改为容器的话，层级过深
     * 后续处理
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public CommViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == HEADER_VIEW) {
            return CommViewHolder.getViewHolder(parent, mHeaderViews.get(0));
        } else if (viewType == FOOTER_VIEW) {
            return CommViewHolder.getViewHolder(parent, mFooterViews.get(0));
        } else {
            return CommViewHolder.getViewHolder(parent, layoutId);
        }
    }

    @Override
    public void onBindViewHolder(CommViewHolder holder, @SuppressLint("RecyclerView") final int position) {
        int index;
        int type = getItemViewType(position);
        if (type == NORMAL_VIEW) {
            index = position - getHeaderCount();
            convert(holder, mData.get(index));
            if (onItemClickListener != null) {
                holder.getItemView().setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        onItemClickListener.onItemClick(v, position - getHeaderCount());
                    }
                });
            }
            if (isOpenAnim) {
                if (!isFirstOnly || position > lastPostion) {
                    if (customAnimator != null) {
                        setAnimator = customAnimator;
                    }
                    for (Animator anim : setAnimator.getAnimators(holder.getItemView())) {
                        anim.setDuration(mDuration).start();
                        anim.setInterpolator(mInterpolator);
                    }
                    lastPostion = position;
                }
            }
        }
    }

    public abstract void convert(CommViewHolder holder, T t);

    @Override
    public int getItemCount() {
        return mData.size() + getHeaderCount() + getFooterCount();
    }

    public void setDatas(List<T> data) {
        this.mData = data;
        notifyDataSetChanged();
    }

    public void addAll(List<T> data) {
        int index = getItemCount() - 1 + getHeaderCount();
        this.mData.addAll(data);
        notifyItemRangeChanged(index, data.size());
    }
    public void setNewData(List<T> data) {
        this.mData = data;
        notifyDataSetChanged();
    }

    public void addData(int position, T item) {
        if (mData.size() > position) {
            int index = position + getHeaderCount();
            this.mData.add(position, item);
            notifyItemInserted(index);
        } else {
            addData(item);
        }
    }
    public void addData(T item) {
        this.mData.add(item);
        notifyItemInserted(getItemCount() - 1 - getFooterCount());
    }

    public void removeData(int position) {
        if (mData.size() > position) {
            int index = position + getHeaderCount();
            this.mData.remove(position);
            notifyItemRemoved(index);
        }
    }

    private OnItemClickListener onItemClickListener;

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    @Override
    public int getItemViewType(int position) {
        if (position < getHeaderCount()) {
            return HEADER_VIEW;
        } else if (position > getHeaderCount() + mData.size() - 1) {
            return FOOTER_VIEW;
        }
        return getItemDifViewType(position);
    }

    protected int getItemDifViewType(int position) {
        return NORMAL_VIEW;
    }

    protected void setFullSpan(CommViewHolder holder, boolean fullSpan) {
        ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
        if (fullSpan && params != null
                && params instanceof StaggeredGridLayoutManager.LayoutParams) {
            ((StaggeredGridLayoutManager.LayoutParams) params).setFullSpan(true);
        }
    }

    @Override
    public void onViewAttachedToWindow(CommViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        int layoutPosition = holder.getLayoutPosition();
        int itemViewType = getItemViewType(layoutPosition);
        setFullSpan(holder, itemViewType == HEADER_VIEW || itemViewType == FOOTER_VIEW);
    }
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            Log.e(TAG, "onAttachedToRecyclerView: GridLayoutManager" );
            final GridLayoutManager manager = (GridLayoutManager) layoutManager;
            manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int itemViewType = getItemViewType(position);
                    return (itemViewType == HEADER_VIEW ||
                            itemViewType == FOOTER_VIEW ) ? manager.getSpanCount() : 1;
                }
            });
        }
        recyclerView.addOnScrollListener(mOnScrollListener);
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        recyclerView.removeOnScrollListener(mOnScrollListener);
    }

    private boolean canScroll(RecyclerView recyclerView) {
        boolean canScroll = recyclerView.canScrollVertically(1);
        return !canScroll;
    }

    private RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == RecyclerView.SCROLL_STATE_IDLE && canScroll(recyclerView)) {
                if (canLoad && mOnLoadMoreListener != null) {
                    canLoad = false;
                    mOnLoadMoreListener.loadMore();
                }
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
        }
    };
    private OnLoadMoreListener mOnLoadMoreListener;

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.mOnLoadMoreListener = onLoadMoreListener;
        canLoad = true;
    }

    public interface OnLoadMoreListener{
        public void loadMore();
    }

    public void loadComplete() {
        canLoad = true;
        notifyDataSetChanged();
    }

    public T getItem(int position) {
        int index = position - getHeaderCount();
        return mData.get(index);
    }
}
